home *** CD-ROM | disk | FTP | other *** search
/ Sky at Night 2006 September / SAN CD 9-2006 CD-ROM 16.iso / pc / Software / Network Telescope Control / NTC-Setup.Exe / Source / ntc_server_calculus.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  2006-03-24  |  36.7 KB  |  1,896 lines

  1. unit ntc_server_calculus;
  2. {
  3.     Copyright (C) 2004 - 2006 Andrew Sprott
  4.  
  5.     http://astronomy.crysania.co.uk
  6.     astro@trefach.co.uk
  7.  
  8.     This program is free software; you can redistribute it and/or
  9.     modify it under the terms of the GNU General Public License
  10.     as published by the Free Software Foundation; either version 2
  11.     of the License, or (at your option) any later version.
  12.  
  13.     This program is distributed in the hope that it will be useful,
  14.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16.     GNU General Public License for more details.
  17.  
  18.     You should have received a copy of the GNU General Public License
  19.     along with this program; if not, write to the Free Software
  20.     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21. }
  22.  
  23. interface
  24.  
  25. uses
  26.     SysUtils,
  27.     dateutils,
  28.     math,
  29.  
  30.     ntc_server_form;
  31.  
  32. const
  33.     null_entry=0;
  34.     days:array[1..7] of string=(
  35.         'monday',
  36.         'tuesday',
  37.         'wednesday',
  38.         'thursday',
  39.         'friday',
  40.         'saturday',
  41.         'sunday');
  42.     light_speed=1/(3*100000);
  43.  
  44. type
  45.     date_time=record
  46.         hours,
  47.         minutes,
  48.         day,
  49.         day_year,
  50.         date,
  51.         month,
  52.         year:word;
  53.         seconds:double;
  54.         time_zone,
  55.         daylight_savings:integer;
  56.     end;
  57.  
  58.     vector=record
  59.         x:array[1..3] of double;
  60.     end;
  61.  
  62.     row=record
  63.         a:array[1..3] of string[16];
  64.     end;
  65.  
  66.     b_row=record
  67.         b:array[1..3] of double;
  68.     end;
  69.  
  70.     matrix=record
  71.         q:array[1..3] of row;
  72.         r:array[1..3] of b_row;
  73.         binary:boolean;
  74.         arg:double;
  75.     end;
  76.  
  77.     tscope_calculus=class(tobject)
  78.  
  79.         { form handling }
  80.         constructor create;
  81.  
  82.     private
  83.         { private declarations }
  84.         time:tdatetime;
  85.  
  86.         { utilties }
  87.         function get_time(
  88.             time:tdatetime)
  89.             :date_time;
  90.  
  91.         procedure clear_time(
  92.         period:date_time);
  93.  
  94.         { algorithms }
  95.         function date_of_easter(
  96.             period:date_time)
  97.             :date_time;
  98.  
  99.     public
  100.         { Public declarations }
  101.         easter_sunday,
  102.         easter_month:word;
  103.     end;
  104.  
  105. var
  106.     current_calculus:tscope_calculus;
  107.     { put back }
  108.     current_period,
  109.     period_1980,
  110.     period_epoc_1950,
  111.     period_epoc_1979,
  112.     period_epoc_1990:date_time;
  113.     { put back }
  114.  
  115. implementation
  116.  
  117. uses
  118.     ntc_server_observer,
  119.     ntc_server_object;
  120.  
  121.     { -------------
  122.         form handling
  123.         ------------- }
  124.  
  125. constructor tscope_calculus.create;
  126. var
  127.     period:date_time;
  128. begin
  129.     inherited;
  130.     time:=now;
  131.     current_period:=get_time(time);
  132.     period:=date_of_easter(current_period);
  133.     easter_sunday:=period.date;
  134.     easter_month:=period.month;
  135.     with period_1980 do
  136.         begin
  137.             year:=1980;
  138.             month:=1;
  139.             date:=1;
  140.             hours:=0;
  141.             minutes:=0;
  142.             seconds:=0;
  143.         end;
  144.     with period_epoc_1950 do
  145.         begin
  146.             year:=1950;
  147.             month:=1;
  148.             date:=1;
  149.             hours:=0;
  150.             minutes:=0;
  151.             seconds:=0;
  152.         end;
  153.     with period_epoc_1979 do
  154.         begin
  155.             year:=1979;
  156.             month:=6;
  157.             date:=1;
  158.             hours:=0;
  159.             minutes:=0;
  160.             seconds:=0;
  161.         end;
  162.     with period_epoc_1990 do
  163.         begin
  164.             year:=1990;
  165.             month:=1;
  166.             date:=1;
  167.             hours:=0;
  168.             minutes:=0;
  169.             seconds:=0;
  170.         end;
  171. end;
  172.  
  173.     { --------------
  174.         time functions
  175.         -------------- }
  176.  
  177. procedure tscope_calculus.clear_time(
  178.     period:date_time);
  179. begin
  180.     with period do
  181.         begin
  182.             hours:=null_entry;
  183.             minutes:=null_entry;
  184.             seconds:=null_entry;
  185.             day:=null_entry;
  186.             day_year:=null_entry;
  187.             date:=null_entry;
  188.             month:=null_entry;
  189.             year:=null_entry;
  190.             time_zone:=0;
  191.             daylight_savings:=0;
  192.         end;
  193. end;
  194.  
  195. function tscope_calculus.get_time(
  196.     time:tdatetime)
  197.     :date_time;
  198. var
  199.     t:double;
  200. begin
  201.     result.day:=dayofweek(time);
  202.     result.date:=dayofthemonth(time);
  203.     result.day_year:=dayoftheyear(time);
  204.     DecodeDate(time,result.Year,result.month,result.Day_year);
  205.     t:=frac(time)*24;
  206.     result.hours:=trunc(t);
  207.     t:=frac(t)*60;
  208.     result.seconds:=trunc(frac(t)*60);
  209.     result.minutes:=trunc(t);
  210. end;
  211.  
  212.     { --------------
  213.         date of easter
  214.         -------------- }
  215.  
  216. function tscope_calculus.date_of_easter(
  217.     period:date_time)
  218.     :date_time;
  219. var
  220.     exit_period:date_time;
  221.     a,b,c,d,e,f,g,h,i,k,l,m,n,p:word;
  222.     t1:word;
  223. begin
  224.     clear_time(exit_period);
  225.     with period do
  226.         begin
  227.             a:=year mod 19;
  228.             b:=year div 100;
  229.             c:=year mod 100;
  230.             d:=b div 4;
  231.             e:=b mod 4;
  232.             f:=(b+8) div 25;
  233.             g:=(b-f+1) div 3;
  234.             h:=(19*a+b-d-g+15) mod 30;
  235.             i:=c div 4;
  236.             k:=c mod 4;
  237.             l:=(32+2*e+2*i-h-k) mod 7;
  238.             m:=(a+11*h+22*i) div 451;
  239.             t1:=(h+l-7*m+114);
  240.             n:=t1 div 31;
  241.             p:=t1 mod 31;
  242.             date:=p+1;
  243.             month:=n;
  244.         end;
  245. end;
  246.  
  247.     { ---------------
  248.         day of the year
  249.         --------------- }
  250.  
  251. function day_of_year(
  252.     period:tdatetime)
  253.     :word;
  254. begin
  255.     result:=dayoftheyear(period);
  256. end;
  257.  
  258.     { -----------
  259.         julian date
  260.         ----------- }
  261.  
  262. function get_julian(
  263.     period:date_time)
  264.     :double;
  265. var
  266.     y,m,ba,bb,bc:integer;
  267.     bd,d,t:double;
  268. begin
  269.     with period do
  270.         begin
  271.             y:=year;
  272.             m:=month;
  273.             t:=seconds/60;
  274.             t:=(t+minutes)/60;
  275.             t:=(t+hours)/24;
  276.             d:=day+t;
  277.             if m<3 then
  278.                 begin
  279.                     dec(y);
  280.                     inc(m,12);
  281.                 end;
  282.             if (year>1582) or (month>10) or (date>=15) then
  283.                 begin
  284.                     ba:=y div 100;
  285.                     bb:=2-ba+ba div 4;
  286.                 end
  287.             else
  288.                 bb:=0;
  289.             bc:=trunc(365.25*y);
  290.             if y<0 then
  291.                 bc:=trunc(bc-0.75);
  292.             bd:=trunc(30.6001*(m+1));
  293.             result:=bb+bc+bd+d+1720994.5;
  294.         end;
  295. end;
  296.  
  297.     { ----------------------------------
  298.         convert julian day to calendar day
  299.         ---------------------------------- }
  300.  
  301. function julian_to_calendar(
  302.     julian:double)
  303.     :date_time;
  304. var
  305.     bi:integer;
  306.     bf,ba,bb,bc,bd,be,bg,d,m:double;
  307. begin
  308.     julian:=julian+0.5;
  309.     bi:=trunc(julian);
  310.     bf:=frac(julian);
  311.     if bi>2299160 then
  312.         begin
  313.             ba:=trunc((bi-1867216.25)/36524.25);
  314.             bb:=bi+1+ba-trunc(ba/4);
  315.         end
  316.     else
  317.         bb:=bi;
  318.     bc:=bb+1524;
  319.     bd:=trunc((bc-122.1)/365.25);
  320.     be:=trunc(365.25*bd);
  321.     bg:=trunc((bc-be)/30.6001);
  322.     d:=bc-be+bf-trunc(30.6001*bg);
  323.     result.date:=trunc(d);
  324.     d:=frac(d)*24;
  325.     result.hours:=trunc(d);
  326.     d:=frac(d)*60;
  327.     result.minutes:=trunc(d);
  328.     d:=frac(d)*60;
  329.     result.seconds:=d;
  330.     if bg<13.5 then
  331.         m:=bg-1
  332.     else
  333.         m:=bg-13;
  334.     if m>2.5 then
  335.         result.year:=trunc(bd-4716)
  336.     else
  337.         result.year:=trunc(bd-4715);
  338.     result.month:=trunc(m);
  339. end;
  340.  
  341.     { -----------
  342.         day of week
  343.         ----------- }
  344.  
  345. function day_of_week(
  346.     period:date_time)
  347.     :word;
  348. var
  349.     jd,ba:double;
  350. begin
  351.     jd:=get_julian(period);
  352.     ba:=(jd+1.5)/7;
  353.     ba:=trunc(frac(ba)*7);
  354.     if ba=0 then
  355.         ba:=7;
  356.     result:=trunc(ba);
  357. end;
  358.  
  359.     { ---------------
  360.         time to decimal
  361.         --------------- }
  362.  
  363. function time_to_decimal(
  364.     period:date_time)
  365.     :double;
  366. var
  367.     t:double;
  368. begin
  369.     with period do
  370.         begin
  371.             t:=seconds/60;
  372.             t:=(t+minutes)/60;
  373.             t:=t+hours;
  374.             result:=t;
  375.         end;
  376. end;
  377.  
  378.     { ---------------
  379.         decimal to time
  380.         --------------- }
  381.  
  382. function decimal_to_time(
  383.     t:double)
  384.     :date_time;
  385. begin
  386.     result.hours:=trunc(t);
  387.     t:=frac(t)*60;
  388.     result.minutes:=trunc(t);
  389.     result.seconds:=trunc(frac(t)*60);
  390. end;
  391.  
  392.     { ----------------
  393.         local time to ut
  394.         ---------------- }
  395.  
  396. function local_to_ut(
  397.     period:date_time)
  398.     :date_time;
  399. var
  400.     z:double;
  401. begin
  402.     with period do
  403.         begin
  404.             inc(hours,daylight_savings+time_zone);
  405.             z:=time_to_decimal(period);
  406.             z:=z-time_zone;
  407.             if z>24 then
  408.                 z:=z-24;
  409.             if z<0 then
  410.                 z:=z+24;
  411.             result:=decimal_to_time(z);
  412.         end;
  413. end;
  414.  
  415.     { ----------------
  416.         ut to local time
  417.         ---------------- }
  418.  
  419. function ut_to_local(
  420.     period:date_time)
  421.     :date_time;
  422. var
  423.     z:double;
  424. begin
  425.     with period do
  426.         begin
  427.             z:=time_to_decimal(period);
  428.             z:=z+time_zone;
  429.             if z>24 then
  430.                 z:=z-24;
  431.             if z<24 then
  432.                 z:=z+24;
  433.             result:=decimal_to_time(z);
  434.             result.hours:=result.hours+daylight_savings;
  435.         end;
  436. end;
  437.  
  438.     { -----------------------------
  439.         ut to greenwich sidereal time
  440.         ----------------------------- }
  441.  
  442. function ut_to_gst(
  443.     period:date_time)
  444.     :date_time;
  445. var
  446.     jd,ut,bs,bt,bt0:double;
  447.  
  448.     procedure normalise;
  449.     begin
  450.         while bt0>24 do
  451.             bt0:=bt0-24;
  452.         while bt0<24 do
  453.             bt0:=bt0+24;
  454.     end;
  455.  
  456. begin
  457.     jd:=get_julian(period);
  458.     with period do
  459.         begin
  460.             bs:=jd-2451545.0;
  461.             bt:=bs/36525.0;
  462.             bt0:=6.697374558+(2400.051336*bt)+(0.000025862*(power(bt,2)));
  463.             normalise;
  464.             ut:=time_to_decimal(local_to_ut(period));
  465.             ut:=ut*1.002737090;
  466.             bt0:=bt0+ut;
  467.             normalise;
  468.             result:=decimal_to_time(bt0);
  469.         end;
  470. end;
  471.  
  472.     { -----------------------------
  473.         greenwich sidereal time to ut
  474.         ----------------------------- }
  475.  
  476. function gst_to_ut(
  477.     period:date_time)
  478.     :date_time;
  479. var
  480.     jd,ut,bs,bt,bt0:double;
  481.  
  482.     procedure normalise;
  483.     begin
  484.         while bt0>24 do
  485.             bt0:=bt0-24;
  486.         while bt0<24 do
  487.             bt0:=bt0+24;
  488.     end;
  489.  
  490. begin
  491.     jd:=get_julian(period);
  492.     with period do
  493.         begin
  494.             bs:=jd-2451545.0;
  495.             bt:=bs/36525.0;
  496.             bt0:=6.697374558+(2400.051336*bt)+(0.000025862*(power(bt,2)));
  497.             normalise;
  498.             ut:=time_to_decimal(period);
  499.             normalise;
  500.             ut:=ut*0.9972695663;
  501.             result:=decimal_to_time(ut);
  502.         end;
  503. end;
  504.  
  505.     { ----------
  506.         gst to lst
  507.         ---------- }
  508.  
  509. function gst_to_lst(
  510.     period:date_time)
  511.     :date_time;
  512. var
  513.     gst,l:double;
  514. begin
  515.     gst:=time_to_decimal(period);
  516.     with scope_observer do
  517.         begin
  518.             l:=longitude/15;
  519.             if longitude>0 then
  520.                 gst:=gst-l
  521.             else if longitude<0 then
  522.                 gst:=gst+l;
  523.             if gst>24 then
  524.                 gst:=gst-24;
  525.             if gst<0 then
  526.                 gst:=gst+24;
  527.         end;
  528.     result:=decimal_to_time(gst);
  529. end;
  530.  
  531.     { ----------
  532.         lst to gst
  533.         ---------- }
  534.  
  535. function lst_to_gst_decimal(
  536.     lst:double)
  537.     :double;
  538. var
  539.     l:double;
  540. begin
  541.     with scope_observer do
  542.         begin
  543.             l:=longitude/15;
  544.             if longitude>0 then
  545.                 lst:=lst+l
  546.             else if longitude<0 then
  547.                 lst:=lst-l;
  548.             if lst>24 then
  549.                 lst:=lst-24;
  550.             if lst<0 then
  551.                 lst:=lst+24;
  552.         end;
  553.     result:=lst;
  554. end;
  555.  
  556. function lst_to_gst(
  557.     period:date_time)
  558.     :date_time;
  559. var
  560.     lst,gst:double;
  561. begin
  562.     lst:=time_to_decimal(period);
  563.     gst:=lst_to_gst_decimal(lst);
  564.     result:=decimal_to_time(gst);
  565. end;
  566.  
  567.     { ------------------
  568.         degrees to decimal
  569.         ------------------ }
  570.  
  571. function degrees_to_decimal(
  572.     coord:dms)
  573.     :double;
  574. var
  575.     d:double;
  576. begin
  577.     with coord do
  578.         begin
  579.             d:=seconds/60;
  580.             d:=(d+minutes)/60;
  581.             d:=d+degrees;
  582.             result:=d;
  583.         end;
  584. end;
  585.  
  586.     { ------------------
  587.         decimal to degrees
  588.         ------------------ }
  589.  
  590. function decimal_to_degrees(
  591.     d:double)
  592.     :dms;
  593. var
  594.     t:double;
  595. begin
  596.     result.degrees:=trunc(d);
  597.     t:=frac(d)*60;
  598.     result.minutes:=trunc(t);
  599.     result.seconds:=trunc(frac(t)*60);
  600.     result.minutes:=trunc(t);
  601. end;
  602.  
  603.     { -------------
  604.         ra to decimal
  605.         ------------- }
  606.  
  607. function ra_to_decimal(
  608.     coord:hms)
  609.     :double;
  610. var
  611.     t:double;
  612. begin
  613.     with coord do
  614.         begin
  615.             t:=seconds/60;
  616.             t:=(t+minutes)/60;
  617.             t:=t+hours;
  618.             result:=t;
  619.         end;
  620. end;
  621.  
  622.     { -------------
  623.         decimal to ra
  624.         ------------- }
  625.  
  626. function decimal_to_ra(
  627.     t:double)
  628.     :hms;
  629. var
  630.     d:double;
  631. begin
  632.     result.hours:=trunc(t);
  633.     d:=frac(t)*60;
  634.     result.minutes:=trunc(d);
  635.     result.seconds:=trunc(frac(d)*60);
  636.     result.minutes:=trunc(d);
  637. end;
  638.  
  639.     { ----------------------
  640.         right ascension to lst
  641.         ---------------------- }
  642.  
  643. function ra_to_lst(
  644.     period:date_time;
  645.     ra:hms)
  646.     :date_time;
  647. var
  648.     gst,lst:date_time;
  649.     ra_d,t,lst_d:double;
  650. begin
  651.     gst:=ut_to_gst(period);
  652.     lst:=gst_to_lst(gst);
  653.     lst_d:=time_to_decimal(lst);
  654.     ra_d:=ra_to_decimal(ra);
  655.     t:=lst_d-ra_d;
  656.     if t<0 then
  657.         t:=t+24;
  658.     result:=decimal_to_time(t);
  659. end;
  660.  
  661.     { ----------------------
  662.         lst to right ascension
  663.         ---------------------- }
  664.  
  665. function lst_to_ra(
  666.     ra:hms;
  667.     period:date_time)
  668.     :hms;
  669. var
  670.     lst:date_time;
  671.     t,lst_d:double;
  672. begin
  673.     lst:=gst_to_lst(ut_to_gst(period));
  674.     with period do
  675.         begin
  676.             hours:=trunc(ra_to_decimal(ra));
  677.             lst_d:=time_to_decimal(lst);
  678.             t:=lst_d-hours;
  679.             if t<0 then
  680.                 t:=t+24;
  681.         end;
  682.     result:=decimal_to_ra(t);
  683. end;
  684.  
  685.     { ------------------
  686.         ecliptic obliquity
  687.         ------------------ }
  688.  
  689. function ecliptic_obliquity
  690.     :double;
  691. var
  692.     jd,bt,ao:double;
  693. begin
  694.     jd:=get_julian(period_1980);
  695.     jd:=jd-2451545.0;
  696.     bt:=jd/36525.0;
  697.     ao:=46.815*bt+0.0006*power(bt,2)-0.00181*power(bt,3);
  698.     ao:=ao/3600;
  699.     result:=23.439292-ao;
  700. end;
  701.  
  702.     { ------------------------------------
  703.         match degree with signs of quadrants
  704.         ------------------------------------ }
  705.  
  706. procedure match_xy_with_degree(
  707.             x,
  708.             y:double;
  709.     var deg:double);
  710. begin
  711.     if x>=0 then
  712.         begin
  713.             if y>=0 then
  714.                 begin
  715.                     if deg<-360 then
  716.                         deg:=deg+360
  717.                     else if deg<-180 then
  718.                         deg:=deg+180
  719.                     else if deg>360 then
  720.                         deg:=deg-360
  721.                     else if deg>180 then
  722.                         deg:=deg-180;
  723.                 end
  724.             else
  725.                 begin
  726.                     if deg<-270 then
  727.                         deg:=deg+360
  728.                     else if deg<-90 then
  729.                         deg:=deg+180
  730.                     else if deg>270 then
  731.                         deg:=deg-360
  732.                     else if deg>90 then
  733.                         deg:=deg-180;
  734.                 end;
  735.         end
  736.     else
  737.         begin
  738.             if y<0 then
  739.                 begin
  740.                     if deg<-180 then
  741.                         deg:=deg+360
  742.                     else if deg<-360 then
  743.                         deg:=deg+180
  744.                     else if deg>180 then
  745.                         deg:=deg-360
  746.                     else if deg>360 then
  747.                         deg:=deg-180;
  748.                 end
  749.             else
  750.                 begin
  751.                     if deg<-90 then
  752.                         deg:=deg+360
  753.                     else if deg<-270 then
  754.                         deg:=deg+180
  755.                     else if deg>90 then
  756.                         deg:=deg-360
  757.                     else if deg>270 then
  758.                         deg:=deg-180;
  759.                 end;
  760.         end;
  761. end;
  762.  
  763.     { --------
  764.         matrices
  765.         -------- }
  766.  
  767. function setup_v(
  768.     u,
  769.     v:double)
  770.     :vector;
  771. begin
  772.     result.x[1]:=cos(u)*cos(v);
  773.     result.x[2]:=sin(u)*cos(v);
  774.     result.x[3]:=sin(v);
  775. end;
  776.  
  777. function get_ra_dec_vector(
  778.     ra:hms;
  779.     dec:dms)
  780.     :vector;
  781. var
  782.     u,v:double;
  783. begin
  784.     u:=ra_to_decimal(ra);
  785.     v:=degrees_to_decimal(dec);
  786.     result:=setup_v(u,v);
  787. end;
  788.  
  789. function get_degrees_vector(
  790.     u_d:dms;
  791.     v_d:dms)
  792.     :vector;
  793. var
  794.     u,v:double;
  795. begin
  796.     u:=degrees_to_decimal(u_d);
  797.     v:=degrees_to_decimal(v_d);
  798.     result:=setup_v(u,v);
  799. end;
  800.  
  801. procedure process_matrix(
  802.             w:vector;
  803.             m:matrix;
  804.     var v:vector;
  805.             arg:double);
  806. var
  807.     i:integer;
  808.  
  809.     function parse(
  810.         s:string)
  811.         :double;
  812.  
  813.         function check_function(
  814.             i:integer)
  815.             :double;
  816.         var
  817.             t:string;
  818.         begin
  819.             result:=0;
  820.             t:=copy(s,i+5,3);
  821.             if i=1 then
  822.                 begin
  823.                     if t='cos' then
  824.                         result:=cos(arg)
  825.                     else if t='sin' then
  826.                         result:=sin(arg);
  827.                 end
  828.             else
  829.                 begin
  830.                     if t='cos' then
  831.                         result:=-cos(arg)
  832.                     else if t='sin' then
  833.                         result:=-sin(arg);
  834.                 end;
  835.         end;
  836.  
  837.     begin
  838.         if s[1]='-' then
  839.             begin
  840.                 if (s[2]>='0') and (s[2]<='9') then
  841.                     result:=strtofloatdef(s,0)
  842.                 else
  843.                     result:=check_function(2);
  844.             end
  845.         else if (s[1]>='0') and (s[1]<='9') then
  846.             result:=strtofloatdef(s,0)
  847.         else
  848.             result:=check_function(1);
  849.     end;
  850.  
  851. begin
  852.     with m do
  853.          if not binary then
  854.         begin
  855.             for i:=1 to 3 do
  856.                  with q[i],v do
  857.                 w.x[i]:=parse(a[1])*x[1]+parse(a[2])*x[2]+parse(a[3])*x[3];
  858.         end
  859.     else
  860.         begin
  861.             for i:=1 to 3 do
  862.                  with r[i],v do
  863.                 w.x[i]:=b[1]*x[1]+b[2]*x[2]+b[3]*x[3];
  864.         end;
  865. end;
  866.  
  867. procedure get_vector_ra_dec(
  868.     w:vector;
  869.     ra:hms;
  870.     dec:dms);
  871. var
  872.     u,v:double;
  873. begin
  874.     with w do
  875.         begin
  876.             u:=arctan(x[2]/x[1]);
  877.             v:=arcsin(x[3]);
  878.         end;
  879.     ra:=decimal_to_ra(u);
  880.     dec:=decimal_to_degrees(v);
  881. end;
  882.  
  883. procedure get_vector_degrees(
  884.     w:vector;
  885.     lat,
  886.     long:dms);
  887. var
  888.     u,v:double;
  889. begin
  890.     with w do
  891.         begin
  892.             u:=arctan(x[2]/x[1]);
  893.             v:=arcsin(x[3]);
  894.         end;
  895.     lat:=decimal_to_degrees(u);
  896.     long:=decimal_to_degrees(v);
  897. end;
  898.  
  899.     { --------------------------
  900.         local position and horizon
  901.         -------------------------- }
  902.  
  903. procedure horizon_to_localised(
  904.             alt,
  905.             az:dms;
  906.     var hours:hms;
  907.     var    dec:dms);
  908. var
  909.     v,w:vector;
  910.     m:matrix;
  911.     latitude:double;
  912. begin
  913.     v:=get_degrees_vector(alt,az);
  914.     latitude:=scope_observer.latitude;
  915.     with m do
  916.         begin
  917.             arg:=latitude;
  918.             binary:=false;
  919.             q[1].a[1]:='-sin';
  920.             q[1].a[2]:='';
  921.             q[1].a[3]:='cos';
  922.             q[2].a[1]:='';
  923.             q[2].a[2]:='-1';
  924.             q[2].a[3]:='';
  925.             q[3].a[1]:='cos';
  926.             q[3].a[2]:='';
  927.             q[3].a[3]:='sin';
  928.             process_matrix(w,m,v,arg);
  929.         end;
  930.     get_vector_ra_dec(w,hours,dec);
  931. end;
  932.  
  933. procedure localised_to_horizon(
  934.             hours:hms;
  935.             dec:dms;
  936.     var alt,
  937.             az:dms);
  938. var
  939.     v,w:vector;
  940.     m:matrix;
  941.     latitude:double;
  942. begin
  943.     v:=get_ra_dec_vector(hours,dec);
  944.     latitude:=scope_observer.latitude;
  945.     with m do
  946.         begin
  947.             arg:=latitude;
  948.             binary:=false;
  949.             q[1].a[1]:='-sin';
  950.             q[1].a[2]:='';
  951.             q[1].a[3]:='cos';
  952.             q[2].a[1]:='';
  953.             q[2].a[2]:='-1';
  954.             q[2].a[3]:='';
  955.             q[3].a[1]:='cos';
  956.             q[3].a[2]:='';
  957.             q[3].a[3]:='sin';
  958.             process_matrix(w,m,v,arg);
  959.         end;
  960.     get_vector_degrees(w,alt,az);
  961. end;
  962.  
  963.     { ------------------------
  964.         localised and equatorial
  965.         ------------------------ }
  966.  
  967. procedure equatorial_to_localised(
  968.             ra:hms;
  969.             dec:dms;
  970.     var l_ra:hms;
  971.     var l_dec:dms);
  972. var
  973.     v,w:vector;
  974.     m:matrix;
  975.     lst:double;
  976. begin
  977.     v:=get_ra_dec_vector(ra,dec);
  978.     lst:=time_to_decimal(ra_to_lst(current_period,ra));
  979.     with m do
  980.         begin
  981.             arg:=lst;
  982.             binary:=false;
  983.             q[1].a[1]:='cos';
  984.             q[1].a[2]:='sin';
  985.             q[1].a[3]:='';
  986.             q[2].a[1]:='sin';
  987.             q[2].a[2]:='-cos';
  988.             q[2].a[3]:='';
  989.             q[3].a[1]:='';
  990.             q[3].a[2]:='';
  991.             q[3].a[3]:='1';
  992.             process_matrix(w,m,v,arg);
  993.         end;
  994.     get_vector_ra_dec(w,l_ra,l_dec);
  995. end;
  996.  
  997. procedure localised_to_equatorial(
  998.             l_ra:hms;
  999.             l_dec:dms;
  1000.     var    ra:hms;
  1001.     var dec:dms);
  1002. var
  1003.     v,w:vector;
  1004.     m:matrix;
  1005.     lst:double;
  1006. begin
  1007.     v:=get_ra_dec_vector(l_ra,l_dec);
  1008.     lst:=time_to_decimal(ra_to_lst(current_period,ra));
  1009.     with m do
  1010.         begin
  1011.             arg:=lst;
  1012.             binary:=false;
  1013.             q[1].a[1]:='cos';
  1014.             q[1].a[2]:='sin';
  1015.             q[1].a[3]:='';
  1016.             q[2].a[1]:='sin';
  1017.             q[2].a[2]:='-cos';
  1018.             q[2].a[3]:='';
  1019.             q[3].a[1]:='';
  1020.             q[3].a[2]:='';
  1021.             q[3].a[3]:='1';
  1022.             process_matrix(w,m,v,arg);
  1023.         end;
  1024.     get_vector_ra_dec(w,ra,dec);
  1025. end;
  1026.  
  1027.     { -----------------------
  1028.         ecliptic and equatorial
  1029.         ----------------------- }
  1030.  
  1031. procedure equatorial_to_ecliptic(
  1032.             ra:hms;
  1033.             dec:dms;
  1034.     var e_long,
  1035.             e_lat:dms);
  1036. var
  1037.     v,w:vector;
  1038.     m:matrix;
  1039.     obliquity:double;
  1040. begin
  1041.     v:=get_ra_dec_vector(ra,dec);
  1042.     obliquity:=ecliptic_obliquity;
  1043.     with m do
  1044.         begin
  1045.             arg:=obliquity;
  1046.             binary:=false;
  1047.             q[1].a[1]:='1';
  1048.             q[1].a[2]:='';
  1049.             q[1].a[3]:='';
  1050.             q[2].a[1]:='';
  1051.             q[2].a[2]:='cos';
  1052.             q[2].a[3]:='sin';
  1053.             q[3].a[1]:='';
  1054.             q[3].a[2]:='-sin';
  1055.             q[3].a[3]:='cos';
  1056.             process_matrix(w,m,v,arg);
  1057.         end;
  1058.     get_vector_degrees(w,e_long,e_lat);
  1059. end;
  1060.  
  1061. procedure ecliptic_to_equatorial(
  1062.             e_long,
  1063.             e_lat:dms;
  1064.     var ra:hms;
  1065.     var dec:dms);
  1066. var
  1067.     v,w:vector;
  1068.     m:matrix;
  1069.     obliquity:double;
  1070. begin
  1071.     v:=get_degrees_vector(e_long,e_lat);
  1072.     obliquity:=ecliptic_obliquity;
  1073.     with m do
  1074.         begin
  1075.             arg:=obliquity;
  1076.             binary:=false;
  1077.             q[1].a[1]:='1';
  1078.             q[1].a[2]:='';
  1079.             q[1].a[3]:='';
  1080.             q[2].a[1]:='';
  1081.             q[2].a[2]:='cos';
  1082.             q[2].a[3]:='-sin';
  1083.             q[3].a[1]:='';
  1084.             q[3].a[2]:='sin';
  1085.             q[3].a[3]:='cos';
  1086.             process_matrix(w,m,v,arg);
  1087.         end;
  1088.     get_vector_ra_dec(w,ra,dec);
  1089. end;
  1090.  
  1091.     { ----------------------
  1092.         glactic and equatorial
  1093.         ---------------------- }
  1094.  
  1095. procedure equatorial_to_galactic(
  1096.             ra:hms;
  1097.             dec:dms;
  1098.     var g_long,
  1099.             g_lat:dms);
  1100. var
  1101.     v,w:vector;
  1102.     m:matrix;
  1103. begin
  1104.     v:=get_ra_dec_vector(ra,dec);
  1105.     with m do
  1106.         begin
  1107.             arg:=0;
  1108.             binary:=false;
  1109.             q[1].a[1]:='-0.0669887';
  1110.             q[1].a[2]:='-0.8727558';
  1111.             q[1].a[3]:='-0.4835389';
  1112.             q[2].a[1]:='0.4927285';
  1113.             q[2].a[2]:='-0.4503470';
  1114.             q[2].a[3]:='0.7445846';
  1115.             q[3].a[1]:='-0.8676008';
  1116.             q[3].a[2]:='-0.1883746';
  1117.             q[3].a[3]:='0.4601998';
  1118.             process_matrix(w,m,v,arg);
  1119.         end;
  1120.     get_vector_degrees(w,g_long,g_lat);
  1121. end;
  1122.  
  1123. procedure galactic_to_equatorial(
  1124.             g_long,
  1125.             g_lat:dms;
  1126.     var ra:hms;
  1127.     var dec:dms);
  1128. var
  1129.     v,w:vector;
  1130.     m:matrix;
  1131. begin
  1132.     v:=get_degrees_vector(g_long,g_lat);
  1133.     with m do
  1134.         begin
  1135.             arg:=0;
  1136.             binary:=false;
  1137.             q[1].a[1]:='-0.0669887';
  1138.             q[1].a[2]:='-0.8727558';
  1139.             q[1].a[3]:='-0.8676008';
  1140.             q[2].a[1]:='-0.8727558';
  1141.             q[2].a[2]:='-0.4503470';
  1142.             q[2].a[3]:='-0.1883746';
  1143.             q[3].a[1]:='-0.4835389';
  1144.             q[3].a[2]:='0.7445846';
  1145.             q[3].a[3]:='0.4601998';
  1146.             process_matrix(w,m,v,arg);
  1147.         end;
  1148.     get_vector_ra_dec(w,ra,dec);
  1149. end;
  1150.  
  1151.     { ---------------------------------------------
  1152.         find angle between two equatorial coordinates
  1153.         --------------------------------------------- }
  1154.  
  1155. function find_angle(
  1156.     ra_1,
  1157.     ra_2:hms;
  1158.     dec_1,
  1159.     dec_2:dms)
  1160.     :dms;
  1161. var
  1162.     ra_1_d,ra_2_d,
  1163.     dec_1_d,dec_2_d,
  1164.     t,d:double;
  1165. begin
  1166.     ra_1_d:=ra_to_decimal(ra_1);
  1167.     dec_1_d:=degrees_to_decimal(dec_1);
  1168.     ra_2_d:=ra_to_decimal(ra_2);
  1169.     dec_2_d:=degrees_to_decimal(dec_2);
  1170.     t:=(ra_1_d-ra_2_d)*15;
  1171.     d:=sin(dec_1_d)*sin(dec_2_d)+cos(dec_1_d)*cos(dec_2_d)*cos(t);
  1172.     d:=arccos(d);
  1173.     result:=decimal_to_degrees(d);
  1174. end;
  1175.  
  1176.     { --------------------------------------------
  1177.         find rising and setting times for coordinate
  1178.         -------------------------------------------- }
  1179.  
  1180. function rise_and_set(
  1181.             ra:hms;
  1182.             dec:dms;
  1183.     var rising_d,
  1184.             setting_d:double;
  1185.     var rising_az,
  1186.             setting_az:dms;
  1187.     var ang:double)
  1188.             :boolean;
  1189. var
  1190.     ra_d,
  1191.     dec_d,
  1192.     a1,a2,
  1193.     h,u,x,y:double;
  1194. begin
  1195.     ra_d:=ra_to_decimal(ra);
  1196.     dec_d:=degrees_to_decimal(dec);
  1197.     a1:=(sin(dec_d)/cos(scope_observer.latitude));
  1198.     if (a1<1) and (a1>-1) then
  1199.         begin
  1200.             a1:=arccos(a1);
  1201.             result:=true;
  1202.             a2:=360-a1;
  1203.             u:=arccos(sin(scope_observer.latitude)/cos(a2));
  1204.             x:=34/60;
  1205.             { calculate refraction }
  1206.             ang:=arcsin(tan(x)/tan(u));
  1207.             a1:=a1-ang;
  1208.             a2:=a2+ang;
  1209.             rising_az:=decimal_to_degrees(a1);
  1210.             setting_az:=decimal_to_degrees(a2);
  1211.             h:=(1/15)*arccos(-tan(scope_observer.latitude)*tan(dec_d));
  1212.             a1:=24+ra_d+h;
  1213.             if a1>24 then
  1214.                 a1:=a1-24;
  1215.             a2:=ra_d+h;
  1216.             if a2>24 then
  1217.                 a2:=a2-24;
  1218.             { calculate refraction }
  1219.             y:=arcsin(sin(x)/sin(u));
  1220.             ang:=(240/y)/cos(dec_d);
  1221.             ang:=ang/3600;
  1222.             a1:=a1-ang;
  1223.             a2:=a2+ang;
  1224.             rising_d:=lst_to_gst_decimal(a1);
  1225.             setting_d:=lst_to_gst_decimal(a2);
  1226.         end
  1227.     else
  1228.         result:=false;
  1229. end;
  1230.  
  1231.     { ----------
  1232.         precession
  1233.         ---------- }
  1234.  
  1235. procedure precession(
  1236.             ra_1:hms;
  1237.             dec_1:dms;
  1238.     var ra_2:hms;
  1239.     var dec_2:dms);
  1240. var
  1241.     jd1,p1,p2,p3,
  1242.     ra_1_d,dec_1_d,
  1243.     u2,v2:double;
  1244. var
  1245.     v,w,s:vector;
  1246.     m:matrix;
  1247.  
  1248.     procedure precession_variables;
  1249.     begin
  1250.         p1:=0.6406161*jd1+0.0000839*power(jd1,2)+0.0000050*power(jd1,3);
  1251.         p2:=0.6406161*jd1+0.0003041*power(jd1,2)+0.0000051*power(jd1,3);
  1252.         p3:=0.5567530*jd1-0.0001185*power(jd1,2)-0.0000116*power(jd1,3);
  1253.     end;
  1254.  
  1255. begin
  1256.     jd1:=get_julian(period_epoc_1950);
  1257.     jd1:=(jd1-2451545)/36525;
  1258.     precession_variables;
  1259.     with m do
  1260.         begin
  1261.             binary:=true;
  1262.             arg:=0;
  1263.             { cx*ct*cz-sx*sz }
  1264.             r[1].b[1]:=cos(p1)*cos(p3)*cos(p2)-sin(p1)*sin(p2);
  1265.             { cx*ct*sz+sx*cz }
  1266.             r[1].b[2]:=cos(p1)*cos(p3)*sin(p2)+sin(p1)*cos(p2);
  1267.             { cx*st }
  1268.             r[1].b[3]:=cos(p1)*sin(p3);
  1269.             { -sx*ct*cz-cx*sz }
  1270.             r[2].b[1]:=-sin(p1)*cos(p3)*cos(p2)-cos(p1)*sin(p2);
  1271.             { -sx*ct*sz+cx*cz }
  1272.             r[2].b[2]:=-sin(p1)*cos(p3)*sin(p2)+cos(p1)*cos(p2);
  1273.             { -sx*st }
  1274.             r[2].b[3]:=-sin(p1)*sin(p3);
  1275.             { -st*cz }
  1276.             r[3].b[1]:=-sin(p3)*cos(p2);
  1277.             { -st*sz }
  1278.             r[3].b[2]:=-sin(p3)*sin(p2);
  1279.             { ct }
  1280.             r[3].b[3]:=cos(p3);
  1281.         end;
  1282.     ra_1_d:=ra_to_decimal(ra_1);
  1283.     dec_1_d:=degrees_to_decimal(dec_1);
  1284.     v:=setup_v(ra_1_d,dec_1_d);
  1285.     process_matrix(s,m,v,0);
  1286.     jd1:=get_julian(period_epoc_1979);
  1287.     jd1:=(jd1-2451545)/36525;
  1288.     precession_variables;
  1289.     with m do
  1290.         begin
  1291.             { cx*ct*cz-sx*sz }
  1292.             r[1].b[1]:=cos(p1)*cos(p3)*cos(p2)-sin(p1)*sin(p2);
  1293.             { -sx*ct*cz-cx*sz }
  1294.             r[1].b[2]:=-sin(p1)*cos(p3)*cos(p2)-cos(p1)*sin(p2);
  1295.             { -st*cz }
  1296.             r[1].b[3]:=-sin(p3)*cos(p2);
  1297.             { cx*ct*sz+sx*cz }
  1298.             r[2].b[1]:=cos(p1)*cos(p3)*sin(p2)+sin(p1)*cos(p2);
  1299.             { -sx*ct*sz+cx*cz }
  1300.             r[2].b[2]:=-sin(p1)*cos(p3)*sin(p2)+cos(p1)*cos(p2);
  1301.             { -st*sz }
  1302.             r[2].b[3]:=-sin(p3)*sin(p2);
  1303.             { cx*st }
  1304.             r[3].b[1]:=cos(p1)*sin(p3);
  1305.             { -sx*st }
  1306.             r[3].b[2]:=-sin(p1)*sin(p3);
  1307.             { ct }
  1308.             r[3].b[3]:=cos(p3);
  1309.         end;
  1310.     process_matrix(w,m,s,0);
  1311.     with w do
  1312.         begin
  1313.             u2:=arctan(x[2]/x[1]);
  1314.             v2:=arcsin(x[3]);
  1315.             match_xy_with_degree(x[1],x[2],u2);
  1316.         end;
  1317.     ra_2:=decimal_to_ra(u2);
  1318.     dec_2:=decimal_to_degrees(v2);
  1319. end;
  1320.  
  1321.     { --------
  1322.         nutation
  1323.         -------- }
  1324.  
  1325. procedure nutation(
  1326.     period:date_time;
  1327.     var e_long_a,
  1328.             e_ob_a:double);
  1329. var
  1330.     jd,a,b,l,ma:double;
  1331.  
  1332.     procedure keep_in_range(
  1333.         var f:double);
  1334.     begin
  1335.         while f>360 do
  1336.             f:=f-360;
  1337.         while f<0 do
  1338.             f:=f+360;
  1339.     end;
  1340.  
  1341. begin
  1342.     jd:=get_julian(period);
  1343.     jd:=(jd-2415020)/36525;
  1344.     a:=100.002136*jd;
  1345.     l:=279.6967+360*(a-trunc(a));
  1346.     keep_in_range(l);
  1347.     b:=5.372617*jd;
  1348.     ma:=259.1833-360*(b-trunc(b));
  1349.     keep_in_range(ma);
  1350.     e_long_a:=-17.2*sin(ma)-1.3*sin(2*l);
  1351.     e_ob_a:=9.2*cos(ma)+0.5*cos(2*l);
  1352. end;
  1353.  
  1354.     { ----------
  1355.         aberration
  1356.         ---------- }
  1357.  
  1358. procedure aberration(
  1359.     var e_long,
  1360.             e_lat:dms;
  1361.             s_e_long:dms);
  1362. var
  1363.     e_long_d,e_lat_d,s_e_long_d:double;
  1364. begin
  1365.     e_long_d:=degrees_to_decimal(e_long);
  1366.     e_lat_d:=degrees_to_decimal(e_lat);
  1367.     s_e_long_d:=degrees_to_decimal(s_e_long);
  1368.     e_long_d:=e_long_d+(-20.5*cos(s_e_long_d-e_long_d)/cos(e_lat_d))/3600;
  1369.     e_lat_d:=e_lat_d+(-20.5*sin(s_e_long_d-e_long_d)*sin(e_lat_d))/3600;
  1370.     e_long:=decimal_to_degrees(e_long_d);
  1371.     e_lat:=decimal_to_degrees(e_lat_d);
  1372. end;
  1373.  
  1374.     { ----------
  1375.         refraction
  1376.         ---------- }
  1377.  
  1378. procedure refraction(
  1379.             alt:dms;
  1380.             p,
  1381.             t:double;
  1382.     var a_alt:dms);
  1383. var
  1384.     z,alt_d:double;
  1385. begin
  1386.     alt_d:=degrees_to_decimal(alt);
  1387.     if alt_d>15 then
  1388.         begin
  1389.             z:=90-alt_d;
  1390.             alt_d:=alt_d+(0.00452*p*tan(z)/(273+t));
  1391.         end
  1392.     else
  1393.          alt_d:=alt_d+
  1394.         (p*(0.1594+0.0196*alt_d+0.00002*power(alt_d,2)))/
  1395.         ((273+t)*(1+0.505*alt_d+0.0845*power(alt_d,2)));
  1396.     a_alt:=decimal_to_degrees(alt_d);
  1397. end;
  1398.  
  1399.     { -------------------
  1400.         geocentric parallax
  1401.         ------------------- }
  1402.  
  1403. procedure geocentric_parallax(
  1404.             lat:dms;
  1405.             h:double;
  1406.     var p_sin_l,
  1407.             p_cos_l:double);
  1408. var
  1409.     u,lat_d:double;
  1410. begin
  1411.     lat_d:=degrees_to_decimal(lat);
  1412.     u:=arctan(0.996647*tan(lat_d));
  1413.     h:=(h/6378140);
  1414.     p_sin_l:=0.996647*sin(u);
  1415.     p_cos_l:=cos(u)+h*cos(lat_d);
  1416. end;
  1417.  
  1418.     { ------------------------------------------
  1419.         correct for geocentric parallax for object
  1420.         ------------------------------------------ }
  1421.  
  1422. procedure correct_for_parallax(
  1423.             period:date_time;
  1424.             au,
  1425.             height:double;
  1426.             lat:dms;
  1427.             ra:hms;
  1428.             dec:dms;
  1429.     var a_ra:hms;
  1430.     var a_dec:dms);
  1431. var
  1432.     lst:date_time;
  1433.     pie,h,a1,a2,
  1434.     ra_d,ra_dd,dec_d,dec_dd,p_cos_l,p_sin_l:double;
  1435. begin
  1436.     pie:=(8.794/au)/3600/15;
  1437.     lst:=gst_to_lst(ut_to_gst(period));
  1438.     ra_d:=ra_to_decimal(ra);
  1439.     dec_d:=degrees_to_decimal(dec);
  1440.     geocentric_parallax(lat,height,p_sin_l,p_cos_l);
  1441.     h:=ra_to_decimal(lst_to_ra(ra,lst));
  1442.     a1:=(pie*sin(h)*p_cos_l)/cos(dec_d);
  1443.     ra_dd:=ra_d-a1;
  1444.     a2:=(pie*(p_sin_l*cos(dec_d)-p_cos_l*cos(h)*sin(dec_d)));
  1445.     dec_dd:=dec_d-a2;
  1446.     a_ra:=decimal_to_ra(ra_dd);
  1447.     a_dec:=decimal_to_degrees(dec_dd);
  1448. end;
  1449.  
  1450.     { ===========================================
  1451.         planets, asteroids, binary stars and comets
  1452.         =========================================== }
  1453.  
  1454.  
  1455.  
  1456.     { ==============================
  1457.         heliographic coordinates [sun]
  1458.         ============================== }
  1459.  
  1460.     { -----------------------
  1461.         calculate suns position
  1462.         ----------------------- }
  1463.  
  1464. procedure suns_position(
  1465.             period:date_time;
  1466.     var ra:hms;
  1467.     var dec:dms;
  1468.     var distance,
  1469.             size,
  1470.             e_long_d:double);
  1471. var
  1472.     jd,jd_1990,n,m,e_long_e1990_d,e_long_p_d,ecc_d,ecc_r,
  1473.     ec,a,e,ae,v,f,sapc:double;
  1474.     done:boolean;
  1475. begin
  1476.     jd_1990:=get_julian(period_epoc_1990);
  1477.     jd:=get_julian(period)-jd_1990;
  1478.     n:=(360/365.242191)*trunc(jd);
  1479.     while n<0 do
  1480.         n:=n+360;
  1481.     while n>360 do
  1482.         n:=n-360;
  1483.     e_long_e1990_d:=279.6966778+36000.76892+0.0003025*power(jd_1990,2);
  1484.     e_long_p_d:=281.2208444+1.719175*jd_1990+0.000452778*power(jd_1990,2);
  1485.     ecc_d:=0.01675104-0.0000418*jd_1990-0.000000126*power(jd_1990,2);
  1486.     m:=n+e_long_e1990_d-e_long_p_d;
  1487.     if ecc_d<=0.1 then
  1488.         begin
  1489.             ecc_r:=ecc_d*(pi/180);
  1490.             e:=m;
  1491.             done:=false;
  1492.             while not done do
  1493.                 begin
  1494.                     a:=e-ecc_r*sin(e)-m;
  1495.                     done:=a<=0.000001;
  1496.                     if not done then
  1497.                         begin
  1498.                             ae:=a/(1-ecc_r*cos(e));
  1499.                             e:=ae;
  1500.                         end;
  1501.                 end;
  1502.             v:=sqrt((1+ecc_r)/(1-ecc_r))*tan(e/2);
  1503.             v:=(arctan(v)*2)*(180/pi);
  1504.             e_long_d:=v+e_long_e1990_d;
  1505.             if e_long_d<0 then
  1506.                 e_long_d:=e_long_d+360
  1507.             else if e_long_d>360 then
  1508.                 e_long_d:=e_long_d-360;
  1509.         end
  1510.     else
  1511.         begin
  1512.             if m<0 then
  1513.                 m:=m+360;
  1514.             ec:=360/pi*ecc_d*sin(m);
  1515.             v:=m+ec;
  1516.             e_long_d:=n+ec+e_long_e1990_d;
  1517.             if e_long_d>360 then
  1518.                 e_long_d:=e_long_d-360;
  1519.         end;
  1520.     f:=(1+ecc_d*cos(v))/(1-power(ecc_d,2));
  1521.     distance:=(1.495985/f)*power(10,8);
  1522.     size:=f*0.533128;
  1523.     sapc:=distance/light_speed;
  1524.     sapc:=360/365.242191*(sapc/60/60/24);
  1525.     e_long_d:=e_long_d-sapc;
  1526.     ecliptic_to_equatorial(
  1527.         decimal_to_degrees(e_long_d),
  1528.         decimal_to_degrees(0),
  1529.         ra,dec);
  1530. end;
  1531.  
  1532.     { -----------------------
  1533.         find coordinates of sun
  1534.         ----------------------- }
  1535.  
  1536. procedure find_sunspot(
  1537.             period:date_time;
  1538.             pos_angle,
  1539.             displacement:dms;
  1540.     var h_long_c,
  1541.             h_lat_c:double;
  1542.     var h_long,
  1543.             h_lat:dms);
  1544. var
  1545.     jd,t,an_long,x,y,a,m,ad1,ad2,o,
  1546.     p_axis,pos_ang_d,dis_d,rad_d,p,size,
  1547.     h_lat_d,h_long_d,distance,gd:double;
  1548.     ra:hms;
  1549.     dec,tp:dms;
  1550. begin
  1551.     jd:=get_julian(period);
  1552.     t:=(jd-2415020)/36525;
  1553.     a:=84*t/60;
  1554.     tp.degrees:=74;
  1555.     tp.minutes:=22;
  1556.     tp.seconds:=0;
  1557.     suns_position(period,ra,dec,distance,size,gd);
  1558.     an_long:=degrees_to_decimal(tp)+a;
  1559.     y:=sin(an_long-gd)*cos(7.25);
  1560.     x:=-cos(an_long-gd);
  1561.     a:=arctan(y/x);
  1562.     match_xy_with_degree(x,y,a);
  1563.     m:=(360/25.38)*(jd-2398220);
  1564.     while m>360 do
  1565.         m:=m-360;
  1566.     m:=360-m;
  1567.     a:=a+m;
  1568.     if a>360 then
  1569.         a:=a-360;
  1570.     h_long_d:=a;
  1571.     h_lat_d:=arcsin(sin(gd-an_long)*sin(7.25));
  1572.     h_long_c:=h_long_d;
  1573.     h_lat_c:=h_lat_d;
  1574.     o:=ecliptic_obliquity;
  1575.     ad1:=arctan(-cos(gd)*tan(o));
  1576.     ad2:=arctan(-cos(an_long-gd)*tan(7.25));
  1577.     p_axis:=ad1+ad2;
  1578.     dis_d:=degrees_to_decimal(displacement);
  1579.     rad_d:=size/2;
  1580.     p:=arcsin(dis_d/rad_d)-dis_d;
  1581.     pos_ang_d:=degrees_to_decimal(pos_angle);
  1582.     h_lat_d:=
  1583.         arcsin((sin(h_lat_d)*cos(p)+cos(h_lat_d)*sin(p)*cos(p_axis-pos_ang_d)));
  1584.     a:=arcsin((sin(p)*sin(p_axis-pos_ang_d)/(cos(h_lat_d))));
  1585.     h_long_d:=h_long_d+a;
  1586.     if h_long_d>360 then
  1587.         h_long_d:=h_long_d-360;
  1588.     h_lat:=decimal_to_degrees(h_lat_d);
  1589.     h_long:=decimal_to_degrees(h_long_d);
  1590. end;
  1591.  
  1592.     { ------------------
  1593.         sunrise and sunset
  1594.         ------------------ }
  1595.  
  1596. procedure sunrise_and_sunset(
  1597.             period:date_time;
  1598.             longitude,
  1599.             latitude:dms;
  1600.             height:double;
  1601.     var rises,
  1602.             sets:date_time);
  1603. var
  1604.     midnight:date_time;
  1605.     ra,ra_b,ra_a,a_ra:hms;
  1606.     dec,dec_b,a_dec,dec_a,blank:dms;
  1607.     distance,size,ang,ang_1,ang_2,a_lat,c,x,a_dec_d,
  1608.     gst_r_1,gst_r_2,gst_s_1,gst_s_2,gst_r,gst_s,
  1609.     gd,gd_b,gd_a,long_d,gst_0,gst_0_ut:double;
  1610.     zero_lat:dms;
  1611. begin
  1612.     midnight:=period;
  1613.     with midnight do
  1614.         begin
  1615.             hours:=0;
  1616.             minutes:=0;
  1617.             seconds:=0;
  1618.         end;
  1619.     suns_position(period,ra,dec,distance,size,gd);
  1620.     gd_b:=gd-0.985647;
  1621.     with zero_lat do
  1622.         begin
  1623.             degrees:=0;
  1624.             minutes:=0;
  1625.             seconds:=0;
  1626.         end;
  1627.     ecliptic_to_equatorial(decimal_to_degrees(gd_b),zero_lat,ra_b,dec_b);
  1628.     rise_and_set(ra_b,dec_b,gst_r_1,gst_s_1,blank,blank,ang_1);
  1629.     gd_a:=gd+0.985647;
  1630.     ecliptic_to_equatorial(decimal_to_degrees(gd_a),zero_lat,ra_a,dec_a);
  1631.     rise_and_set(ra_a,dec_a,gst_r_2,gst_s_2,blank,blank,ang_2);
  1632.     if gd_b>gd_a then
  1633.         begin
  1634.             gst_r_2:=gst_r_2+24;
  1635.             gst_s_2:=gst_s_2+24;
  1636.         end;
  1637.     gst_0:=time_to_decimal(ut_to_gst(period));
  1638.     long_d:=degrees_to_decimal(longitude);
  1639.     long_d:=long_d/15*1.002738;
  1640.     gst_0_ut:=gst_0-long_d;
  1641.     if gst_0_ut<0 then
  1642.         gst_0_ut:=gst_0_ut+24;
  1643.     if gd_b<gst_0_ut then
  1644.         begin
  1645.             gst_r_1:=gst_r_1+24;
  1646.             gst_s_1:=gst_s_1+24;
  1647.             gst_r_2:=gst_r_2+24;
  1648.             gst_s_2:=gst_s_2+24;
  1649.         end;
  1650.     gst_r:=(24.07*gst_r_1-gst_0*(gst_r_2-gst_r_1))/(24.07+gst_r_1-gst_r_2);
  1651.     gst_s:=(24.07*gst_s_1-gst_0*(gst_s_2-gst_s_1))/(24.07+gst_s_1-gst_s_2);
  1652.     correct_for_parallax(period,distance,height,latitude,ra,dec,a_ra,a_dec);
  1653.     a_lat:=(degrees_to_decimal(dec_b)+degrees_to_decimal(dec_a))/2;
  1654.     ang:=(ang_1+ang_2)/2;
  1655.     a_dec_d:=degrees_to_decimal(a_dec);
  1656.     x:=(size/2)/(-a_dec_d+ang);
  1657.     c:=-(a_lat+ang+x)/3600;
  1658.     gst_r:=gst_r-c;
  1659.     gst_s:=gst_s+c;
  1660.     rises:=midnight;
  1661.     with rises do
  1662.         begin
  1663.             rises:=decimal_to_time(gst_r);
  1664.             rises:=gst_to_ut(rises);
  1665.             rises:=ut_to_local(rises);
  1666.         end;
  1667.     sets:=midnight;
  1668.     with sets do
  1669.         begin
  1670.             sets:=decimal_to_time(gst_s);
  1671.             sets:=gst_to_ut(sets);
  1672.             sets:=ut_to_local(sets);
  1673.         end;
  1674. end;
  1675.  
  1676. procedure twilight(
  1677.             period:date_time;
  1678.     var evening,
  1679.             morning:date_time;
  1680.     var all_night:boolean);
  1681. var
  1682.     ra:hms;
  1683.     dec:dms;
  1684.     rises,sets:date_time;
  1685.     h1,h2,t,r,s,
  1686.     dec_d,distance,size,e_long_d:double;
  1687. begin
  1688.     with scope_observer do
  1689.         begin
  1690.             with period do
  1691.                 begin
  1692.                     hours:=12;
  1693.                     minutes:=0;
  1694.                     seconds:=0;
  1695.                 end;
  1696.             suns_position(period,ra,dec,distance,size,e_long_d);
  1697.             dec_d:=degrees_to_decimal(dec);
  1698.             h1:=arccos(-tan(latitude)*tan(dec_d));
  1699.             h2:=(cos(108)-sin(latitude)*sin(dec_d))/(cos(latitude)*cos(dec_d));
  1700.             if (h2<1) and (h2>-1) then
  1701.                 begin
  1702.                     all_night:=false;
  1703.                     h2:=arccos(h2);
  1704.                 t:=((h2-h1)/15)*0.9973;
  1705.                     sunrise_and_sunset(period,
  1706.                         decimal_to_degrees(longitude),
  1707.                         decimal_to_degrees(latitude),
  1708.                         height,rises,sets);
  1709.                     r:=time_to_decimal(rises);
  1710.                     r:=r-t;
  1711.                     morning:=decimal_to_time(r);
  1712.                     s:=time_to_decimal(sets);
  1713.                     s:=s+t;
  1714.                     evening:=decimal_to_time(s);
  1715.                 end
  1716.             else
  1717.                 begin
  1718.                     morning:=period;
  1719.                     evening:=period;
  1720.                     all_night:=true;
  1721.                 end;
  1722.         end;
  1723. end;
  1724.  
  1725.     { ------------------------------------
  1726.         calculate carrington rotation number
  1727.         ------------------------------------ }
  1728.  
  1729. function get_crn(
  1730.     period:date_time)
  1731.     :integer;
  1732. var
  1733.     jd:double;
  1734. begin
  1735.     jd:=get_julian(period);
  1736.     result:=round(1690+((jd-2444235.34)/272753));
  1737. end;
  1738.  
  1739.     { ----------------
  1740.         equation of time
  1741.         ---------------- }
  1742.  
  1743. function equation_of_time(
  1744.     period:date_time)
  1745.     :hms;
  1746. var
  1747.     ra:hms;
  1748.     dec:dms;
  1749.     midday:date_time;
  1750.     distance,size,e_long_d,ut:double;
  1751. begin
  1752.     suns_position(period,ra,dec,distance,size,e_long_d);
  1753.     with period do
  1754.         begin
  1755.             hours:=ra.hours;
  1756.             minutes:=ra.minutes;
  1757.             seconds:=ra.seconds;
  1758.         end;
  1759.     midday:=period;
  1760.     with midday do
  1761.         begin
  1762.             hours:=12;
  1763.             minutes:=0;
  1764.             seconds:=0;
  1765.         end;
  1766.     ut:=time_to_decimal(gst_to_ut(midday))-time_to_decimal(gst_to_ut(period));
  1767.     midday:=decimal_to_time(ut);
  1768.     with midday do
  1769.         begin
  1770.             result.hours:=hours;
  1771.             result.minutes:=minutes;
  1772.             result.seconds:=trunc(seconds);
  1773.         end;
  1774. end;
  1775.  
  1776.     { ----------------
  1777.         solar elongation
  1778.         ---------------- }
  1779.  
  1780. function solar_elongation(
  1781.     period:date_time;
  1782.     ra_p:hms;
  1783.     dec_p:dms)
  1784.     :double;
  1785. var
  1786.     ra:hms;
  1787.     dec:dms;
  1788.     distance,size,e_long_d,ra_d,dec_d,ra_p_d,dec_p_d:double;
  1789. begin
  1790.     suns_position(period,ra,dec,distance,size,e_long_d);
  1791.     ra_d:=ra_to_decimal(ra);
  1792.     dec_d:=degrees_to_decimal(dec);
  1793.     ra_p_d:=ra_to_decimal(ra_p);
  1794.     dec_p_d:=degrees_to_decimal(dec_p);
  1795.     ra_p_d:=ra_p_d*15;
  1796.     result:=arccos(
  1797.         (sin(dec_p_d)*sin(dec_d)+cos(ra_p_d-ra_d)*cos(dec_p_d)*cos(dec_d)));
  1798. end;
  1799.  
  1800.     { ================================
  1801.         selenographic coordinates [moon]
  1802.         ================================ }
  1803.  
  1804.     { --------------------------------------------
  1805.         correct for geocentric parallax for the moon
  1806.         -------------------------------------------- }
  1807.  
  1808. procedure correct_for_parallax_moon(
  1809.             period:date_time;
  1810.             height:double;
  1811.             moon_p,
  1812.             lat:dms;
  1813.             ra:hms;
  1814.             dec:dms;
  1815.     var a_ra:hms;
  1816.     var a_dec:dms);
  1817. var
  1818.     lst:date_time;
  1819.     a,r,h,hh,ra_d,ra_dd,dec_d,dec_dd,moon_p_d,
  1820.     p_sin_l,p_cos_l:double;
  1821. begin
  1822.     ra_d:=ra_to_decimal(ra);
  1823.     dec_d:=degrees_to_decimal(dec);
  1824.     lst:=gst_to_lst(ut_to_gst(period));
  1825.     h:=ra_to_decimal(lst_to_ra(ra,lst));
  1826.     geocentric_parallax(lat,height,p_sin_l,p_cos_l);
  1827.     moon_p_d:=degrees_to_decimal(moon_p);
  1828.     r:=(1/sin(moon_p_d));
  1829.     a:=arctan((p_cos_l*sin(h))/(r*cos(dec_d)-p_cos_l*cos(h)));
  1830.     hh:=h+a;
  1831.     a:=a/15;
  1832.     ra_dd:=ra_d-a;
  1833.     dec_dd:=arctan(cos(hh)*(r*sin(dec_d)-p_sin_l)/r*cos(dec_d)*cos(h)-p_cos_l);
  1834.     a_ra:=decimal_to_ra(ra_dd);
  1835.     a_dec:=decimal_to_degrees(dec_dd);
  1836. end;
  1837.  
  1838.     { ------------------------
  1839.         find coordinates of moon
  1840.         ------------------------ }
  1841.  
  1842. procedure find_crater(
  1843.             period:date_time;
  1844.             geo_lat,
  1845.             m_geo_long,
  1846.             m_geo_lat:dms;
  1847.     var m_long,
  1848.             m_lat,
  1849.             pos_angle:dms);
  1850. var
  1851.     m_geo_long_d,m_geo_lat_d,geo_lat_d,an_long,jd,t,bc,lc,c1,c2,o,f,a,
  1852.     x,y,sx,sy:double;
  1853. begin
  1854.     jd:=get_julian(period);
  1855.     t:=(jd-2451545)/36525;
  1856.     an_long:=125.044522-1934.136261*t;
  1857.     while an_long>360 do
  1858.         an_long:=an_long-360;
  1859.     while an_long<0 do
  1860.         an_long:=an_long+360;
  1861.     f:=93.271910+483202.0175*t;
  1862.     while f>360 do
  1863.         f:=f-360;
  1864.     while f<0 do
  1865.         f:=f+360;
  1866.     geo_lat_d:=degrees_to_decimal(geo_lat);
  1867.     m_geo_long_d:=degrees_to_decimal(m_geo_long);
  1868.     m_geo_lat_d:=degrees_to_decimal(m_geo_lat);
  1869.     bc:=arcsin(-cos(geo_lat_d)*sin(m_geo_lat_d)+sin(geo_lat_d)*
  1870.         cos(m_geo_lat_d)*sin(an_long-m_geo_long_d));
  1871.     y:=(-sin(m_geo_lat_d)*sin(geo_lat_d)-cos(m_geo_lat_d)*
  1872.         cos(geo_lat_d)*sin(an_long-m_geo_long_d));
  1873.     sy:=y;
  1874.     x:=cos(m_geo_lat_d)*cos(an_long-m_geo_long_d);
  1875.     sx:=x;
  1876.     a:=arctan(y/x);
  1877.     match_xy_with_degree(sx,sy,a);
  1878.     lc:=f-a;
  1879.     if lc>10 then
  1880.         lc:=lc-360;
  1881.     if lc<-10 then
  1882.         lc:=lc+360;
  1883.     c1:=arctan((cos(an_long-m_geo_long_d)-sin(geo_lat_d)/
  1884.         (cos(m_geo_lat_d*cos(geo_lat_d)+sin(m_geo_lat_d)*sin(geo_lat_d)*
  1885.          sin(an_long-m_geo_long_d)))));
  1886.     o:=ecliptic_obliquity;
  1887.     c2:=arctan((sin(o)*cos(m_geo_long_d))/(sin(o)*sin(m_geo_lat_d)*
  1888.         sin(m_geo_long_d)-cos(o)*cos(m_geo_lat_d)));
  1889.     m_long:=decimal_to_degrees(lc);
  1890.     m_lat:=decimal_to_degrees(bc);
  1891.     pos_angle:=decimal_to_degrees(c1+c2);
  1892. end;
  1893.  
  1894. end.
  1895.  
  1896.